export abstract class LocalCache {
  /** 缓存键的统一前缀（命名空间） */
  private static namespace: string = 'app:'

  /**
   * 设置命名空间（统一前缀）
   * @param ns 要设置的命名空间
   */
  static setNamespace(ns: string): void {
    this.namespace = ns.endsWith(':') ? ns : `${ns}:` // 确保命名空间以分隔符结尾，增强键名可读性
  }

  /**
   * 获取带命名空间的完整键名
   * @param key 原始键名
   * @returns 带命名空间的键名
   */
  private static getFullKey(key: string): string {
    return this.namespace + key
  }

  /**
   * 存储数据到 localStorage
   * @param key 缓存键名
   * @param value 缓存值
   * @param expired 过期时间(毫秒)，0表示永不过期
   */
  static set<T = any>(key: string, value: T, expired: number = 0): void {
    const fullKey = this.getFullKey(key)
    expired = expired > 0 ? Date.now() + expired * 1000 : 0 //  计算过期时间点，当前时间 + 过期毫秒数
    const data = { value, expired }
    localStorage.setItem(fullKey, JSON.stringify(data))
  }

  /**
   * 从 localStorage 获取数据
   * @param key 缓存键名
   * @returns 缓存值，如果过期或不存在则返回 null
   */
  static get<T = any>(key: string): T | null {
    const fullKey = this.getFullKey(key)
    const jsonStr: string | null = localStorage.getItem(fullKey)
    if (!jsonStr) return null
    try {
      const data: { value: T; expired: number } = JSON.parse(jsonStr)
      const isExpired: boolean = data.expired > 0 && Date.now() > data.expired
      if (!isExpired) return data.value
      localStorage.removeItem(fullKey) // 解析失败时删除无效数据
      return null
    } catch (error) {
      localStorage.removeItem(fullKey) // 解析失败时删除无效数据
      return null
    }
  }

  /**
   * 从 localStorage 删除数据
   * @param key 缓存键名
   */
  static remove(key: string): void {
    const fullKey = this.getFullKey(key)
    localStorage.removeItem(fullKey)
  }

  /**
   * 清空当前命名空间下的所有缓存
   */
  static clearNamespace(): void {
    const keys = Object.keys(localStorage)
    const nsKeys = keys.filter((item) => item.startsWith(this.namespace))
    nsKeys.forEach((key) => localStorage.removeItem(key))
  }

  /**
   * 清空 localStorage 所有数据（谨慎使用）
   */
  static clearAll(): void {
    localStorage.clear()
  }
}
